<?php

namespace App\V3\V3_2_7\Services;

use App\Services\CommonService;
use App\Services\MessageService;
use App\V3\V3_2_7\Models\LogInStorageModel;
use App\V3\V3_2_7\Models\MaterielTypeModel;
use App\V3\V3_2_7\Models\StorageBatchModel;
use App\V3\V3_2_7\Models\StorageManageModel;
use App\V3\V3_2_7\Models\StorageModel;
use App\V3\V3_2_7\Models\StorageShelfLocationModel;
use App\V3\V3_2_7\Models\StorageShelfModel;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ScanCodeInStorageService
{

    /**
     *扫码入库-基地
     * Author: zlf
     * Created at 2024/6/28 16:03
     * @param $data
     * @return array|null
     */
    public static function scanCodeInStorage($data): ?array
    {
        $result = [];
        //仓库扫码入库
        if (!empty($data['storage_id'])) {
            $result = self::storageCodeInStorage($data);
        }

        //货架扫码入库
        if (!empty($data['shelf_id'])) {
            $result = self::shelfCodeInStorage($data);
        }
        //库位扫码入库
        if (!empty($data['location_id'])) {
            $result = self::locationCodeInStorage($data);
        }
        return $result;
    }

    /**
     *仓库扫码入库
     * Author: zlf
     * Created at 2024/6/28 15:51
     * @param $data
     * @return array|null
     */
    public static function storageCodeInStorage($data, $operType = 0): ?array
    {
        if (!$operType)
            DB::beginTransaction();
        try {
            $goodsInfo = MaterielTypeModel::query()->where([
                'id' => $data['type_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($goodsInfo))
                throw new \RuntimeException("无商品信息！");
            $storageInfo = StorageModel::query()->where([
                'id' => $data['storage_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($storageInfo))
                throw new \RuntimeException("无仓库信息！");
            $shelfIds = StorageShelfModel::query()
                ->where([
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'storage_id' => $data['storage_id']
                ])->pluck('id');
            if (empty($shelfIds->toArray()))
                throw new \RuntimeException("无货架信息！");
            $shelfIds = $shelfIds->toArray();
            if (!StorageShelfLocationModel::query()
                ->where([
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'storage_id' => $data['storage_id'],
                ])->whereIn('shelf_id', $shelfIds)
                ->exists())
                throw new \RuntimeException("无库位信息！");
            $locationList = StorageShelfLocationModel::query()
                ->where([
                    'status' => 1,
                    'location_type' => 2,
                    ['standard_num', '>', 0],
                    'main_id' => $data['main_id']
                ])->whereIn('shelf_id', $shelfIds)->get();

            if (!empty($locationList->toArray())) {
                //多个货架的多个库位设置了标准数量处理
                $locationList = $locationList->toArray();
                self::multiShelfLocationHandle($goodsInfo, $storageInfo, $locationList, $data);
            } else {
                $shelfId = StorageShelfModel::query()
                    ->where([
                        'storage_id' => $data['storage_id'],
                        'main_id' => $data['main_id'],
                        'status' => 1,
                        'shelf_type' => 1
                    ])->value('id');
                //默认货架库位入库前处理
                self::defShelfLocationHandle($goodsInfo, $storageInfo, $shelfId, $data);
            }
            if (!$operType)
                DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (\Exception $e) {
            if (!$operType)
                DB::rollBack();
            Log::debug('扫码入库（孵化）异常：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     *货架扫码入库
     * Author: zlf
     * Created at 2024/6/28 15:47
     * @param $data
     * @return array
     */
    public static function shelfCodeInStorage($data, $operType = 0): ?array
    {
        if (!$operType)
            DB::beginTransaction();
        try {
            $goodsInfo = MaterielTypeModel::query()->where([
                'id' => $data['type_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($goodsInfo))
                throw new \RuntimeException("无商品信息！");
            $shelfInfo = StorageShelfModel::query()
                ->where([
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'id' => $data['shelf_id']
                ])->first();
            if (empty($shelfInfo))
                throw new \RuntimeException("无货架信息！");
            $storageInfo = StorageModel::query()->where([
                'id' => $shelfInfo['storage_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($storageInfo))
                throw new \RuntimeException("无仓库信息！");
            if (!StorageShelfLocationModel::query()
                ->where([
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'storage_id' => $shelfInfo['storage_id'],
                    'shelf_id' => $shelfInfo['id']
                ])->exists())
                throw new \RuntimeException("无库位信息！");
            $locationList = StorageShelfLocationModel::query()
                ->where([
                    'main_id' => $data['main_id'],
                    'status' => 1,
                    'location_type' => 2,
                    ['standard_num', '>', 0],
                    'storage_id' => $shelfInfo['storage_id'],
                    'shelf_id' => $shelfInfo['id']
                ])->get();

            if (!empty($locationList->toArray())) {
                //多个库位设置了标准数量处理
                $locationList = $locationList->toArray();
                self::multiShelfLocationHandle($goodsInfo, $storageInfo, $locationList, $data);
            } else {
                $shelfId = StorageShelfModel::query()
                    ->where([
                        'storage_id' => $shelfInfo['storage_id'],
                        'main_id' => $data['main_id'],
                        'status' => 1,
                        'shelf_type' => 1
                    ])->value('id');
                //默认货架库位入库前处理
                self::defShelfLocationHandle($goodsInfo, $storageInfo, $shelfId, $data);
            }
            if (!$operType)
                DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (\Exception $e) {
            if (!$operType)
                DB::rollBack();
            Log::debug('扫码入库（孵化）异常：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    /**
     *库位打码入库
     * Author: zlf
     * Created at 2024/6/28 16:05
     * @param $data
     * @return array
     */
    public static function locationCodeInStorage($data, $operType = 0)
    {
        if (!$operType)
            DB::beginTransaction();
        try {
            $goodsInfo = MaterielTypeModel::query()->where([
                'id' => $data['type_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($goodsInfo))
                throw new \RuntimeException("无商品信息！");
            $locationInfo = StorageShelfLocationModel::query()
                ->where([
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'id' => $data['location_id'],
                ])->first();
            if (empty($locationInfo))
                throw new \RuntimeException("无库位信息！");
            $storageInfo = StorageModel::query()->where([
                'id' => $locationInfo['storage_id'],
                'main_id' => $data['main_id'],
                'delete_flag' => 0,
            ])->first();
            if (empty($storageInfo))
                throw new \RuntimeException("无仓库信息！");
            $shelfInfo = StorageShelfModel::query()
                ->where([
                    'status' => 1,
                    'main_id' => $data['main_id'],
                    'id' => $locationInfo['shelf_id']
                ])->first();
            if (empty($shelfInfo))
                throw new \RuntimeException("无货架信息！");
            $manageInfo = StorageManageModel::query()->where([
                'type_id' => $data['type_id'],
                'storage_id' => $storageInfo['id'],
                'shelf_id' => $shelfInfo['id'],
                'location_id' => $locationInfo['id'],
                'delete_flag' => 0
            ])->first();
            self::InStorage($goodsInfo, $storageInfo, $manageInfo, $shelfInfo['id'], $locationInfo['id'], $data);
            if (!$operType)
                DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        } catch (\Exception $e) {
            if (!$operType)
                DB::rollBack();
            Log::debug('扫码入库（孵化）异常：' . var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //多个货架库位
    private static function multiShelfLocationHandle($goodsInfo, $storageInfo, $locationList, $data): void
    {
        foreach ($locationList as $lVal) {
            $locationId = $lVal['id'];
            $lCond = [
                'location_id' => $lVal['id'],
                'storage_id' => $storageInfo['id'],
                'shelf_id' => $lVal['shelf_id'],
                'delete_flag' => 0
            ];

            $totalNum = StorageManageModel::query()
                ->where($lCond)->sum('in_storage_num');

            /*if (!empty($totalNum)) {*/
            $lCond['type_id'] = $data['type_id'];
            $manInfo = StorageManageModel::query()
                ->where($lCond)->first();
            //现有总库存加操作数量小于等于当前库位设置的标准数量
            if ($totalNum + $data['num'] <= $lVal['standard_num'] && $data['num'] > 0) {
                //echo $data['num'] . 'fail====';die;
                self::InStorage(
                    $goodsInfo,
                    $storageInfo,
                    $manInfo,
                    $lVal['shelf_id'],
                    $lVal['id'],
                    $data,
                );
                $data['num'] = 0;
                break;
            } else {
                //现有总库存加操作数量大于当前库位设置的标准数量
                //操作数量20,总库存数量10，库位01标准数量10;不计算
                //操作数量20,总库存数量3，库位02标准数量10;20-(10-3）= 13
                //操作数量13,总库存数量3，库位03标准数量10;13-(10-3）= 6
                //操作数量6,总库存数量5，库位03标准数量10;6-(10-5）= 1 情况1：没有入库完，还剩一个直接入库到默认库位
                //操作数量6,总库存数量4，库位03标准数量10;6-(10-4）= 0 情况2：剩余操作数量小于等于剩余空间数量，直接入完
                if ($totalNum < $lVal['standard_num'] && $data['num'] > 0) {
                    $subNum = $lVal['standard_num'] - $totalNum;
                    if ($data['num'] >= $subNum) {
                        $data['num'] -= $subNum;
                        $data['sub_num'] = $subNum;
                        //echo $data['sub_num'],'=====';
                        self::InStorage(
                            $goodsInfo,
                            $storageInfo,
                            $manInfo,
                            $lVal['shelf_id'],
                            $lVal['id'],
                            $data
                        );
                    }
                }
                unset($data['sub_num']);
            }
            /*}*/
        }
        //dump_dug($data['num'] . 'seucc==');
        //剩余的入库数量添加到默认货架库位
        if ($data['num'] > 0) {
            //默认货架库位入库前处理
            $shelfId = StorageShelfModel::query()
                ->where([
                    'storage_id' => $storageInfo['id'],
                    'main_id' => $data['main_id'],
                    'status' => 1,
                    'shelf_type' => 1
                ])->value('id');
            self::defShelfLocationHandle($goodsInfo, $storageInfo, $shelfId, $data);
        }
    }

    //默认货架库位入库前处理
    private static function defShelfLocationHandle($goodsInfo, $storageInfo, $shelfId, $data): void
    {
        $locationId = StorageShelfLocationModel::query()
            ->where([
                'main_id' => $data['main_id'],
                'status' => 1,
                'location_type' => 1,
                'shelf_id' => $shelfId
            ])->value('id');
        if (empty($locationId))
            throw new \RuntimeException("无库位信息！");
        $manageInfo = StorageManageModel::query()->where([
            'type_id' => $data['type_id'],
            'storage_id' => $storageInfo['id'],
            'shelf_id' => $shelfId,
            'location_id' => $locationId,
            'delete_flag' => 0
        ])->first();
        self::InStorage($goodsInfo, $storageInfo, $manageInfo, $shelfId, $locationId, $data);
    }

    //入库
    private static function InStorage($goodsInfo, $storageInfo, $manageInfo, $shelfId, $locationId, $data): void
    {
        $inStorageNum = 0;
        $data['num'] = !empty($data['sub_num']) ? $data['sub_num'] : $data['num'];
        if (!empty($manageInfo)) {
            $inStorageNum = $manageInfo->in_storage_num;
            $manageInfo->in_storage_num += $data['num'];
            $manageInfo->save();
            $manageId = $manageInfo['id'];
        } else {
            $manageId = StorageManageModel::query()->insertGetId([
                'materiel_class_id' => $goodsInfo['materiel_class_id'],//物料二级分类id
                'materiel_class_name' => $goodsInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => empty($goodsInfo['class_no']) ? '' : $goodsInfo['class_no'],//物料二级分类名称
                'type_id' => $goodsInfo['id'],//物料id
                'materiel_name' => $goodsInfo['materiel_name'],//物料名称
                'type_name' => $goodsInfo['type_name'],//物料型号名称
                'materiel_no' => $goodsInfo['materiel_no'],//物料编号
                'materiel_mean_cost' => $goodsInfo['cost'] ?? '',
                'storage_id' => $storageInfo['id'],
                'storage_name' => $storageInfo['storage_name'],//仓库名
                'storage_address' => $storageInfo['storage_address'],//仓库地址
                'in_storage_num' => $data['num'],//采购单内物料商品入库数量
                'main_id' => $data['main_id'],//主账号id
                'in_storage_time' => $data['time'],//入库时间
                'alert_num' => 0,
                'created_at' => $data['time'],
                'shelf_id' => $shelfId,
                'location_id' => $locationId,
            ]);
        }
        $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
        do {
            $batchNo = $data['batch_title'] . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
        } while (StorageBatchModel::query()->where([
            'batch_no' => $batchNo,
            'delete_flag' => 0
        ])->exists());
        $batchId = StorageBatchModel::query()->insertGetId([
            'batch_no' => $batchNo,
            'storage_manage_id' => $manageId,
            'batch_num' => $data['num'],
            'batch_left_num' => $data['num'],
            'batch_cost' => $goodsInfo['cost'] ?? '',
            'materiel_id' => 0,
            'main_id' => $data['main_id'],
            'created_at' => $data['time']
        ]);
        //入库操作记录
        $inLogId = LogInStorageModel::query()->insertGetId([
            'type' => !empty($data['type']) ? $data['type'] : 4,//日志类型;0:入库;1:调拨入库;2:直接入库;4扫码入库
            'storage_id' => $storageInfo['id'],//入库目标仓库id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'last_storage_id' => 0,//调拨前所在仓库id
            'curr_storage_manage_id' => $manageId,
            'materiel_class_id' => $goodsInfo['materiel_class_id'],//物料二级分类id
            'materiel_class_name' => $goodsInfo['class_name'],//物料二级分类名称
            'materiel_type_id' => $goodsInfo['id'],//物料id
            'materiel_name' => $goodsInfo['materiel_name'],//物料名称
            'type_name' => $goodsInfo['type_name'],//物料型号名称
            'materiel_no' => $goodsInfo['materiel_no'],//物料编号
            'operate_num' => $data['num'],//操作数量
            'last_storage_num' => $inStorageNum,//操作前库存数
            'next_storage_num' => $inStorageNum + $data['num'],//操作后库存数
            'materiel_mean_cost' => $goodsInfo['cost'] ?? '',//物料均价
            'in_storage_time' => $data['time'],//入库时间
            'code_allocate_no' => !empty($data['code_allocate_no']) ? $data['code_allocate_no'] : '',
            'all_id_type' => !empty($data['all_id_type']) ? $data['all_id_type'] : 0,//单据类型;0:无;1:报溢;2:报损;3:采购;
            'user_id' => $data['user_id'],//操作人id
            'main_id' => $data['main_id'],//主账号id
            'created_at' => $data['time'],
            'serial_number' => '',
            'shelf_id' => $shelfId,
            'label_id' => $data['label_id'] ?? '',
            'location_id' => $locationId,
            'batch_id' => $batchId,
            'batch_no' => $batchNo
        ]);
        MessageService::sendInSms(
            '无',
            $goodsInfo['materiel_name'],
            $goodsInfo['type_name'],
            $storageInfo['id'],
            $storageInfo['storage_name'],
            $data,
            $data['num'],
            $inStorageNum + $data['num'],
            $inLogId
        );
        CommonService::cancelAlertFlag($data['main_id']);
        $logData = '商品名称：' . $goodsInfo['materiel_name'] .
            '入库数量 ' . $data['num'] . ',仓库名：' . $storageInfo['storage_name'];
        CommonService::operateResult($data['user_id'], $data['time'], $data, $logData);
    }
}
